package com.fantasy.data2template;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.fantasy.excel.ReadExcel;
import com.fantasy.file.GetFolderAbsPath;
import com.fantasy.file.ReadTxt;
import com.fantasy.readproperties.ReadProperties;
import com.fantasy.string.StringUtils;

public class Data2Template {

	private static String[] header;
	private static String[] dataFormat;
	private static List<HashMap<String, String>> dataList;
	private static String regex;
	private static int dataLength;
	private static String configFileName = "data2template.properties";
	private static String fileType = ReadProperties.getProperty(configFileName, "fileType");
	private static int places = Integer.valueOf(ReadProperties.getProperty(configFileName, "places"));
	private static int roundType = Integer.valueOf(ReadProperties.getProperty(configFileName, "roundType"));
	private static String[] removeData = ReadProperties.getProperty(configFileName, "removeData").split("\\|");
	private static String xyType = ReadProperties.getProperty(configFileName, "xyType");
	
	public static HashMap<String , String > String2Map(String data){
		String[] datas = data.split(regex);
		int dataLength = header.length;
		HashMap<String, String> dataMap = new HashMap<String ,String>();
		for (int i = 0; i < dataLength ; i ++) {
			if(i >= datas.length){
				dataMap.put(header[i], "");
			}else{
				dataMap.put(header[i], datas[i]);
			}
		}
		return dataMap;
	}
	
	public static void readTxt(String path){
		System.out.println("readTxt:" + path);
		dataList = new ArrayList<HashMap<String, String>>();
		BufferedReader bufReader = ReadTxt.GetBufferReader(path);
		String data;
		try {
			header = bufReader.readLine().split(regex);
			data = bufReader.readLine();
			//System.out.println("startTxt:" + data);
			while(null != data){
				dataList.add(String2Map(data));
				data = bufReader.readLine();
			}
			bufReader.close();
		} catch (IOException e) {
			try {
				bufReader.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
	}
	
	public static void readxls(String path){
		System.out.println("readxls:" + path);
		dataList = new ArrayList<HashMap<String, String>>();
		Workbook wb = ReadExcel.getWorkbook(path);
		Sheet st = wb.getSheetAt(0);
		if("Y".equals(xyType)){
			System.out.println("Ytype");
			readxlsWithYType(st);
		}else if("X".equals(xyType)){
			System.out.println("Xtype");
			readxlsWithXType(st);
		}
	}
	
	/**
	 * 
	 *读取Excel数据为横向排列的如：id   1 2 3 
	 *						 type x y z
	 * */
	public static void readxlsWithXType(Sheet st){
		int rowNum = st.getLastRowNum() + 1;
		header = new String[rowNum];
		for(int rowInx = 0 ; rowInx < rowNum ; rowInx ++){
			Row row = st.getRow(rowInx);
			header[rowInx] = ReadExcel.getCellFormatValue(row.getCell(0));
			int cellLsatNum = row.getLastCellNum();
			for (int colInx = 1 ; colInx < cellLsatNum ; colInx ++) {
				if(dataList.size() < colInx){
					HashMap<String, String> dataMap = new HashMap<String ,String>();
					dataList.add(dataMap);
				}
				dataList.get(colInx - 1).put(header[rowInx], ReadExcel.getCellFormatValueSetPlaces(row.getCell(colInx) ,places, roundType));
			}
		}
	}
	
	/**
	 * 
	 * 读取Excel数据为竖直排列的，如：id  type
	 * 						    1   x
	 * 						    2	y
	 * */
	public static void readxlsWithYType(Sheet st){
		int rowNum = st.getLastRowNum() + 1;
		for(int rowInx = 0 ; rowInx < rowNum ; rowInx ++){
			Row row = st.getRow(rowInx);
			int cellLsatNum = row.getLastCellNum();
			if(rowInx == 0){
				header = new String[cellLsatNum];
				for (int colInx = 0 ; colInx < cellLsatNum ; colInx ++) {
					header[colInx] = ReadExcel.getCellFormatValue(row.getCell(colInx));
				}
			}else{
				HashMap<String, String> dataMap = new HashMap<String ,String>();
				for (int colInx = 0 ; colInx < cellLsatNum ; colInx ++) {
					dataMap.put(header[colInx], ReadExcel.getCellFormatValueSetPlaces(row.getCell(colInx) ,places, roundType));
				}
				dataList.add(dataMap);
			}
		}
	}
	
	public static void getExcelFormat(String path){
		System.out.println("getformat:" + path);
		Workbook wb = ReadExcel.getWorkbook(new File(path));
		Sheet sheet = wb.getSheetAt(0);
		Row row = sheet.getRow(Integer.valueOf(ReadProperties.getProperty(configFileName ,"excelDataFormatRow")) - 1);
		//System.out.println(Integer.valueOf(ReadProperties.read("Txt2excel.properties").getProperty("excelDataFormatRow")) -1);
		dataFormat = new String[row.getLastCellNum()];
		dataLength = row.getLastCellNum();
		for (int i = 0 ; i < row.getLastCellNum() ; i++) {
			Cell cell = row.getCell(i);
			dataFormat[i] = ReadExcel.getCellFormatValue(cell);
			//System.out.println("============" + ReadExcel.getCellFormatValue(cell));
		}
		
	}
	
	public static void writeToExcel(String templateFolder , String resultFolder , String fileName){
		System.out.println("writeToExcel:" + resultFolder + "\\" + fileName + "-result.xls");
		File f= new File(templateFolder + "\\" + fileName + ".xls");
		try {
			Workbook wb = ReadExcel.getWorkbook(f);
			Sheet sheet = wb.getSheetAt(0);
			int dataStartRowInx = Integer.valueOf(ReadProperties.getProperty(configFileName ,"excelDataFormatRow")) -1;
			for(int i = 0 ; i < dataList.size(); i ++){
				Row row = sheet.createRow(dataStartRowInx);
				for (int j = 0 ; j < dataLength ; j++) {
					String cellValue = getFormatString(dataList.get(i), dataFormat[j]);
					for (String str : removeData) {
						cellValue = cellValue.replace(str, "");
					}
					if("".equals(cellValue.trim())){
						
					}else{
						Cell cell = row.createCell(j);
						setCellValue(cell, cellValue, j);
					}
				}
				dataStartRowInx = dataStartRowInx + 1 ;
			}
			FileOutputStream fileOut = new FileOutputStream(resultFolder + "\\" + fileName + "-result.xls");
			wb.write(fileOut);
			fileOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public static void setCellValue(Cell cell , String value , int dataFormatIndex){
		//System.out.println("value : " + value + ">>>>>");
		if(isDecimal(value)){
			Double d = Double.valueOf(value);
			cell.setCellValue(d);
		}else{
			cell.setCellValue(value);
		}
	}
	
	public static boolean isDecimal(String str){  
		return Pattern.compile("([1-9]+[0-9]*|0)(\\.[\\d]+)?").matcher(str).matches();  
	}
	
	public static String getFormatString(HashMap<String,String> data, String format){
		//formatString = format.replace("{@}", data);
		ArrayList<String> regMat = StringUtils.getStrings(format, "\\{[^}]*\\}");
		ArrayList<String> formatStringList = new ArrayList<String>();
		for(String mat : regMat){
			formatStringList.add(analysis(mat , data));
		}
		if(formatStringList.size() == 0){
			return format;
		}
		String surplus;
		//System.out.println("format:" + format + " >> res:" + formatStringList.get(0)
		//		+ "  >>regmat :" + regMat.get(0));
		if(formatStringList.get(0) == null){
			surplus = format.replace(regMat.get(0), "");
			//System.out.println("11111" + surplus);
		}else{
			surplus = format.replace(regMat.get(0), formatStringList.get(0));
			//System.out.println("2222" + surplus);
		}
		//System.out.println("data-Format >> data:" + data + ">>>> format : " + format + " result: " + formatStringList.get(0) );
		return surplus;
	}
	
	private static String analysis(String mat , HashMap<String, String > data) {
		mat = mat.replace("{", "").replace("}", "");
		//System.out.println("mat : " + mat);
		if(mat.startsWith("if")){
			//1>2?3:1;
			int charInx = 2 ;
			String charStr = "";
			String formula = "if";
			int formulaVarInx = 0;
			HashMap<String, String > formulaVarMap = new HashMap<String, String>();
			for(int i = charInx ; i < mat.length() ; i ++ ){
				//System.out.println("charStr:" + charStr);
				charStr = mat.substring(charInx, i);
				if("@".equals(charStr)){
					i = mat.indexOf("#", charInx);
					formulaVarMap.put(formulaVar[formulaVarInx], mat.substring(charInx , i));
					formula = formula + formulaVar[formulaVarInx];
					formulaVarInx ++;
					charInx = i + 1;
				}
				for(String sign : calculateSign){
					if(sign.equals(charStr)){
						formula = formula + sign;
						charInx = i ;
						i = mat.indexOf("?", charInx);
						formulaVarMap.put(formulaVar[formulaVarInx], mat.substring(charInx , i));
						formula = formula + formulaVar[formulaVarInx];
						formula = formula + "?";
						formulaVarInx ++;
						charInx = i +1 ;
						i = mat.indexOf(":", charInx);
						formulaVarMap.put(formulaVar[formulaVarInx], mat.substring(charInx , i));
						formula = formula + formulaVar[formulaVarInx];
						formula = formula + ":";
						formulaVarInx ++;
						charInx = i +1;
						formulaVarMap.put(formulaVar[formulaVarInx], mat.substring(charInx));
						formula = formula + formulaVar[formulaVarInx];
						formulaVarInx ++;
						charInx = i ;
					}
				}
			}
			String result = getFormulaVar(formula , formulaVarMap , data);
			if( result == null){
				return "";
			}else{
				return result;
			}
		}
		if(mat.startsWith("@")){
			return data.get(mat.replace("@", ""));
		}
		return mat;
	}
	
	private static String getFormulaVar(String formula , HashMap<String , String> formulaVarMap ,  HashMap<String , String> data) {
		//System.out.println("formula:" + formula );
		String varA = getFormulaVarValue("A" , formulaVarMap , data);
		String varB = getFormulaVarValue("B" , formulaVarMap , data);
		String varC = getFormulaVarValue("C" , formulaVarMap , data);
		String varD = getFormulaVarValue("D" , formulaVarMap , data);
		//System.out.println("varA:" + varA + " varB:" + varB + " varC:" + varC + " varD:" + varD);
		if("ifA>B?C:D".equals(formula)){
			long aa = Long.parseLong(varA);
			long bb = Long.parseLong(varB);
			
			if(aa > bb){
				return varC;
			}else{
				return varD;
			}
		}
		
		if("ifA<B?C:D".equals(formula)){
			long aa = Long.parseLong(varA);
			long bb = Long.parseLong(varB);
			
			if(aa < bb){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifA=B?C:D".equals(formula)){
			long aa = Long.parseLong(varA);
			long bb = Long.parseLong(varB);
			
			if(aa == bb){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifAendwithB?C:D".equals(formula)){
			
			if(varA.endsWith(varB)){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifAstartwithB?C:D".equals(formula)){
			if(varA.startsWith(varB)){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifAequalsB?C:D".equals(formula)){
			if(varA.equals(varB)){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifAnoequalsB?C:D".equals(formula)){
			if(!varA.equals(varB)){
				return varC;
			}else{
				return varD;
			}
		}
		if("ifAcontainsB?C:D".equals(formula)){
			if(varA.contains(varB)){
				return varC;
			}else{
				return varD;
			}
		}
		return varD;
	}
	
	public static String getFormulaVarValue(String formulaVar , HashMap<String , String> formulaVarMap ,  HashMap<String , String> data){
		String result = "";
		if(formulaVarMap.get(formulaVar) !=null && formulaVarMap.get(formulaVar).startsWith("@")){
			//System.out.println(formulaVarMap.get(formulaVar).substring(1));
			result = data.get(formulaVarMap.get(formulaVar).substring(1));
		}else{
			result = formulaVarMap.get(formulaVar);
		}
		if(result == null){
			result = "";
		}
		return result;
	}

	public static String[] calculateSign = {">","=","<","<>","endwith","startwith","equals","noequals","contains"};
	
	public static String[] formulaVar = {"A","B","C","D","E","F","G","H","I","J","K"};
	
	public static void analysisFormula(){
		
	}

	public static String getFileName(String fileName){
		fileName = fileName.substring(fileName.lastIndexOf("\\") + 1 , fileName.lastIndexOf("."));
		return fileName;
	}
	
	/**
	 * 处理的文件过滤,过滤器
	 */
	private static FileFilter filter = new FileFilter() {
		public boolean accept(File pathname) {
			// 只处理：目录 或是 .java文件
			if (pathname.isDirectory()
					|| (pathname.isFile() && pathname.getName().endsWith(
							fileType))) {
				return true;
			} else {
				return false;
			}
		}
	};
	
	public static void main(String[] args) {
		//String path = "\\\\tsad\\Department\\MIS\\Current Data\\MIS2015\\Common\\MFG-Pro\\QAD-2015EE-Setup\\Setup\\Fantasy\\supplier";
		String basePath = GetFolderAbsPath.getPath();
		String dataFolder = basePath + "\\" + ReadProperties.getProperty(configFileName, "dataFolder");
		String templateFolder = basePath + "\\" + ReadProperties.getProperty(configFileName, "templateFolder");
		String resultFolder = basePath + "\\" + ReadProperties.getProperty(configFileName, "resultFolder");
		
		regex = ReadProperties.getProperty(configFileName ,"dataRegex").replace("|", "\\|");
		File f = new File(dataFolder);
		for (File childF : f.listFiles(filter)) {
			String childFPath = childF.getAbsolutePath();
			getExcelFormat(templateFolder + "\\" + getFileName(childFPath) + ".xls");
			if("txt".equals(fileType)){
				readTxt(childFPath);
			}else if("xls".equals(fileType)){
				readxls(childFPath);
			}
			writeToExcel(templateFolder ,resultFolder , getFileName(childFPath));
		}
		/*
		HashMap<String, String> test = new HashMap<String , String>();
		test.put("aa" , "11");
		test.put("bb" , "22");
		System.out.println(">>" + analysis("{if@aa#=@bb?111:222}" , test) + ">>");
		*/
	}
}
